<template>
  <div v-loading="loading" class="flowTable-container">
    <el-row type="flex" justify="end" align="middle" style="height: 60px; padding:0 10px ">
      <el-col>
        <el-button type="primary" icon="el-icon-back" circle @click="$router.back()" />
      </el-col>
      <el-col>
        <el-row type="flex" justify="end">
          <el-input-number v-model="zoom" style="margin-right:10px" size="small" :step="10" />
          <el-button size="small" type="primary" @click="pubishFlow">发布</el-button>
        </el-row>

      </el-col>

    </el-row>
    <div class="flowTable-content">
      <!-- 画布 -->
      <div id="dashboard_skill_svg" class="svgBox" :style="{transform:`scale(${zoom/100})`}" />
      <el-drawer
        title="选择审批人"
        :visible.sync="showDrawer"
        :show-close="false"
        direction="rtl"
        :close-on-press-escape="false"
        :modal="false"
        :wrapper-closable="false"
      >
        <el-form label-width="120px">
          <el-form-item label="当前审批人">
            <el-select
              v-model="currentUser"
              filterable
              multiple
              style="width:80%"
            >
              <!-- 选择人 -->
              <el-option v-for="item in peoples" :key="item.email" :label="item.userName" :value="item.userName" />
            </el-select>
          </el-form-item>
        </el-form>
        <!-- 选择审批人 -->

        <el-row type="flex" justify="end" style="position:absolute;bottom:10px;right: 10px">
          <el-col>
            <el-button size="small" @click="btnCancel">取消</el-button>
            <el-button type="primary" size="small" @click="btnOK">确定</el-button>
          </el-col>
        </el-row>
      </el-drawer>
    </div>
  </div>
</template>

<script>
import * as d3 from 'd3'
// import Cascader from '@/components/Cascader'
import { getBPMXMLInfo, publishBpmFile, getUserList } from '@/api/approval'
import '@/styles/flow.scss' // 引入样式表
// import DrawEnum from '@/constant/drawInfo'
export default {
  name: 'Dashboard',
  data() {
    return {
      // 当前路程的Id
      bpmId: this.$route.params.id,
      startEvent: null, // 开始节点
      endEvent: null, // 结束节点
      userTask: [], // 用户任务
      relations: [], // 流程之间的关系
      bpmInfo: {}, // 流程信息
      bpmInfoId: null, // 流程文件中的id
      peoples: [], // 人群
      currentUser: [], // 当前用户选择人
      currentEditData: null, // 当前编辑节点数据对象
      currentEditNode: null, // 当前编辑节点D3对象
      showDrawer: false,
      loading: false,
      svg: null,
      zInd: 9,
      zoom: 100,
      canWit: '',
      canHit: 800

    }
  },
  // 获取流程数据

  async mounted() {
    await this.getBPMXMLInfo()
    if (!this.userTask.length) {
      // const newId = this.getNewId()
      // this.userTask = [{
      //   '_activiti:candidateUsers': '${candidateUser2}',
      //   '_activiti:candidateGroups': 'assigneeGroups',
      //   '_activiti:exclusive': 'true',
      //   '_id': newId,
      //   '_name': '新审批人节点'
      // }]
    }
    this.setD3Canvas()
  },
  created() {
    this.getUserList()
  },
  methods: {
    btnOK() {
      const users = this.currentUser.join(',')
      //  选择人
      if (this.currentEditNode) {
        //  更改页面对象的内容
        this.currentEditNode.text(users || '请选择审批人')
      }
      if (this.currentEditData) {
        // 修改数据的内容
        this.currentEditData['_activiti:candidateUsers'] = users || '${candidateUser2}'
        const preIndex = this.userTask.findIndex(item => item._id === this.currentEditData._id)

        // 设置完成后 更新数据
        this.userTask.splice(preIndex, 1, { ...this.currentEditData })
      }
      // 重置数据
      this.currentUser = []
      this.currentEditData = null
      this.currentEditNode = null

      this.showDrawer = false
    },
    btnCancel() {
      this.currentUser = []
      this.currentEditData = null
      this.currentEditNode = null
      this.showDrawer = false
    },
    async getUserList() {
      const { records } = await getUserList({ current: 1, size: 1000 })
      this.peoples = records
    },
    async  getBPMXMLInfo() {
      // 获取路程的文件
      this.loading = true
      const xmlInfo = await getBPMXMLInfo({ processDefinitionId: `${this.bpmId}` })
      const result = this.$x2js.xml2js(xmlInfo)
      this.startEvent = result.definitions.process.startEvent// 开始节点
      this.userTask = result.definitions.process.userTask // 用户任务
      this.endEvent = result.definitions.process.endEvent// 结束节点
      this.relations = result.definitions.process.sequenceFlow // 流程关系
      this.bpmInfo = { ...result.definitions.process }
      this.bpmInfoId = result._id
      this.loading = false
      // this.userTask = this.userTask.map(item => ({ ...item, 'activiti:name': '123' }))
    },
    // 设置画布
    setD3Canvas() {
      this.canWit = this.$el.parentNode.offsetWidth
      this.canHit = this.$el.parentNode.offsetHeight - 130
      this.svg = d3.select('#dashboard_skill_svg') // 选择文档中的body元素
      this.node = this.svg.selectAll('div')
      this.drawBpmInfo(this.data) // 绘制节点
    },
    // 初始化信息
    drawBpmInfo(data) {
      // const _this = this
      this.renderFlowNode() // 渲染流程节点
      this.addEndNode() // 添加流程结束节点
    },
    // 流程节点
    renderFlowNode() {
      console.log(this.userTask)
      const _this = this
      this.node.data(this.userTask)
        .enter()
        .each(function(data) {
          _this.renderNode(d3.select(this), data)
        })
    },
    isStartNode(id) {
      const node = this.relations.find(item => item._sourceRef === this.startEvent._id)
      return node._targetRef === id
    },

    // 生成审核框
    renderNode(node, data) {
      const _this = this
      const isStartNode = this.isStartNode(data._id) // 是否是开始节点
      const titleColor = isStartNode ? '#576A96' : '#FF943E'
      const nodewrap = node.append('div').attr('class', 'node-wrap')
      const content = nodewrap.append('div').attr('class', isStartNode ? 'start-node node-wrap-box' : 'node-wrap-box')
      const title = content.append('div').attr('class', 'title').style('background', titleColor) // 标题
      title.append('span').attr('class', isStartNode ? '' : 'icon iconchaosong') // 图标
      title.append('span').attr('class', 'edit-tit').text(data._name) // 标题内容
      let users = data['_activiti:candidateUsers']
      if (!users || this.isVariableException(users)) {
        users = isStartNode ? '申请人' : '选择审批人'
      }
      console.log(data['_activiti:candidateUsers'])
      content.append('div').attr('class', 'content').text(users) // 选择审批人
        .on('click', function(data) {
          if (!isStartNode) {
            _this.showDrawer = true
            _this.currentEditData = data // 当前编辑的节点数据
            _this.currentEditNode = d3.select(this) // 当前编辑的节点对象
            _this.transNodeToUsersArray() // 转化数据到弹层
          }
        })

      title.append('i').attr('class', 'close').text('x').on('click', function(data) {
        _this.removeNode(data) // 删除数据
        d3.select(this.parentNode.parentNode.parentNode).remove()
      })
      this.renderMark(nodewrap)
    },
    // 生成三角号
    renderMark(node) {
      const _this = this
      node.append('div').attr('class', 'add-node-btn-box').append('div').attr('class', 'add-node-btn').append('div').attr('class', 'btn')
        .on('click', function(preNode) {
          _this.zInd += 1
          _this.removeAddBox(_this.svg)
          _this.renderAddBox(_this.svg, this.parentNode.parentNode, preNode)
        })
    },

    // 创建新增模块
    // preNode为前一个节点
    renderAddBox(svg, tsNode, preNode) {
      const itemData = [{ name: '审批人', type: 'initApproval' }]
      const node = d3.select(tsNode)
      node.style('z-index', this.zInd)
      const cNode = node.append('div').attr('class', 'addbox')
      cNode.append('span').attr('class', 'cls').on('click', () => this.removeAddBox(svg))

      const ccNode = cNode.append('div').attr('class', 'contBox').selectAll(`div`).data(itemData).enter()
      const cn = ccNode.append('div').attr('class', 'items')
      cn.append('div').attr('class', (data) => {
        if (data.type === 'initApproval') {
          return 'icon iconshenpiren'
        } else if (data.type === 'initCCList') {
          return 'icon iconchaosong'
        } else {
          return 'icon iconfenzhi'
        }
      }).on('click', (data) => {
        if (data.type === 'initCondition') {
          // 添加分支
        } else {
          // 添加审批人
          this.addData(preNode)
          svg.selectAll('div').remove()
          this.setD3Canvas()
        }
      })
      cn.append('div')
        .attr('class', 'text')
        .text(function(d) {
          return d.name
        })
    },
    // 添加审批人节点
    addData(preNode) {
      console.log(preNode)
      const preIndex = this.userTask.findIndex(item => item._id === preNode._id)
      const relationIndex = this.relations.findIndex(item => item._sourceRef === preNode._id) // 关系节点索引
      const newId = this.getNewId() // 获取最新的id
      // 找到插入的节点的下一个节点的起点
      const nextNode = this.relations.find(item => item._sourceRef === preNode._id)
      // 获取添加节点的索引
      if (preIndex > -1) {
        // 添加审批人节点
        this.userTask.splice(preIndex + 1, 0, {
          '_activiti:candidateUsers': '${candidateUser2}',
          '_activiti:candidateGroups': 'assigneeGroups',
          '_activiti:exclusive': 'true',
          '_id': newId,
          '_name': '新审批人节点'
        })
      }
      // 如果存在后续节点
      if (relationIndex > -1) {
        // 改变前一个
        this.relations.splice(relationIndex, 1, {
          ...this.relations[relationIndex],
          _targetRef: newId
        })
        // 插入第二个
        this.relations.splice(relationIndex + 1, 0, {
          _targetRef: nextNode._targetRef,
          _sourceRef: newId,
          _id: this.getNewId()
        })
      }
    },
    // 获取最新的Id
    getNewId() {
      let maxId = 0
      this.userTask.forEach(item => {
        maxId = maxId > parseInt(item._id.substr(1)) ? maxId : parseInt(item._id.substr(1))
      })
      maxId = maxId > parseInt(this.startEvent._id.substr(1)) ? maxId : parseInt(this.startEvent._id.substr(1))
      maxId = maxId > parseInt(this.endEvent._id.substr(1)) ? maxId : parseInt(this.endEvent._id.substr(1))
      this.relations.forEach(item => {
        maxId = maxId > parseInt(item._id.substr(1)) ? maxId : parseInt(item._id.substr(1))
      })
      return `_${maxId + 1}`
    },

    // 删除一个节点
    removeNode(data) {
      // 处理数据
      this.userTask = this.userTask.filter(item => item._id !== data._id)
      const sourceItem = this.relations.find(item => item._targetRef === data._id) // 原有的来源选项
      const sourceIndex = this.relations.findIndex(item => item._targetRef === data._id) // 原有的来源id
      const targetItem = this.relations.find(item => item._sourceRef === data._id) // 原有的目标xuan
      const targetIndex = this.relations.findIndex(item => item._sourceRef === data._id) // 原有的目标id
      // 先删除目标数据
      this.relations.splice(targetIndex, 1)
      // 再更新来源数据的节点
      this.relations.splice(sourceIndex, 1, { ...sourceItem, _targetRef: targetItem._targetRef })
    },
    // 移除新增模块
    removeAddBox(svg) {
      const dt = svg.select('.addbox')
      dt.remove()
    },
    // 添加node节点
    addEndNode() {
      const { _name } = this.endEvent
      const endNode = this.svg.append('div').attr('class', 'end-node')
      endNode.append('div').attr('class', 'end-node-circle')
      endNode.append('div').attr('class', 'end-node-text').text(_name)
    },
    // 发布流程
    async pubishFlow() {
      try {
        await this.$confirm('当前配置的流程将发布为当前流程最新版本,确定要进行此操作?')
        const data = new FormData()
        data.append('file', this.createBpmFile()) // 上传文件
        await publishBpmFile(data)
        // this.createBpmFile()
        this.$message.success('部署流程成功')
        this.$router.push('/approval') // 跳到审批列表页面
        // 拼装js数据
      } catch (error) {
        console.log(error)
      }
    },
    // 判断是否是变量表达式
    isVariableException(val) {
      return new RegExp('\\$\\{(.*?)\\}', 'gm').test(val)
    },
    // 转化节点数据到当前用户列表
    transNodeToUsersArray() {
      if (this.currentEditData['_activiti:candidateUsers'] && !this.isVariableException(this.currentEditData['_activiti:candidateUsers']) && this.currentEditData['_activiti:candidateUsers'] !== '选择审批人') {
        // 如果不是默认的变量形式
        this.currentUser = this.currentEditData['_activiti:candidateUsers'].split(',')
      }
    },
    // 创建流程文件
    createBpmFile() {
      // 将json文件生成
      const json = { process: { ...this.bpmInfo, startEvent: this.startEvent, endEvent: this.endEvent, userTask: this.userTask, sequenceFlow: this.relations }}
      console.log(json)
      const xml = this.$x2js.js2xml(json) // 将json转化成xml
      const xmlTemplate = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <definitions id="${this.bpmInfoId}" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath"  name="" targetNamespace="http://www.activiti.org/testm1609143960968" typeLanguage="http://www.w3.org/2001/XMLSchema">
        ${xml}
      </definitions>`
      const xmlFile = new File([xmlTemplate], 'myFirst.bpmn', {
        type: 'text/plain'
      }) // 创建文件对象
      console.log(xmlTemplate)
      return xmlFile
    },

    // 缩放整体视图
    zoomHandle(st) {
      if (st === 'in') {
        this.zoom = this.zoom >= 200 ? 200 : this.zoom + 10
      } else {
        this.zoom = this.zoom <= 50 ? 50 : this.zoom - 10
      }
    }
  }
}
</script>
